package com.hugehard.ImageFilter;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ImageFilterActivity extends Activity implements
		View.OnClickListener, ServiceConnection {
	private Button btnFilter;
	private Button btnStop;
	private TextView textIntValue;
	private Messenger mServiceMessenger = null;
	boolean mIsBound;

	private static boolean active = false;
	private boolean mIsSelectingPicture = false;
	private boolean mIsFinishFiltering = false;
	private boolean mIsHighQuality = false;
	private String mSelectedImagePath = null;

	public static ContentResolver contentResolver;
	public static final String KEY_BITMAP = "bitmap";
	private static final String LOGTAG = "ImageFilterActivity";
	private static final int SELECT_PICTURE = 1;
	private final Messenger mMessenger = new Messenger(
			new IncomingMessageHandler());

	private ServiceConnection mConnection = this;

	private Bitmap mImage = null;
	private ImageView mImageView = null;
	private ProgressDialog mProgressDialog = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		contentResolver = getContentResolver();

		btnFilter = (Button) findViewById(R.id.button1);
		btnStop = (Button) findViewById(R.id.button2);
		textIntValue = (TextView) findViewById(R.id.textViewTime);
		mImageView = (ImageView) findViewById(R.id.imageView);

		mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
		btnFilter.setEnabled(false);
		btnStop.setOnClickListener(this);
		btnFilter.setOnClickListener(this);
		mImageView.setOnClickListener(this);

		startService(new Intent(ImageFilterActivity.this,
				ProcessingService.class));
		doBindService();
		automaticBind();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.layout.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.exitMenuItem:
			doUnbindService();
			stopService(new Intent(ImageFilterActivity.this,
					ProcessingService.class));
			android.os.Process.killProcess(android.os.Process.myPid());
			break;
		case R.id.imageQualitySubMenu:
			if (mIsHighQuality) {
				item.getSubMenu().getItem(1).setChecked(true);
			} else {
				item.getSubMenu().getItem(0).setChecked(true);
			}
			break;
		case R.id.lowQuaMenuItem:
			mIsHighQuality = false;
			break;
		case R.id.highQuaMenuItem:
			mIsHighQuality = true;
			break;
		default:
			super.onOptionsItemSelected(item);
		}
		return true;
	}

	/**
	 * Check if the service is running. If the service is running when the
	 * activity starts, we want to automatically bind to it.
	 */
	private void automaticBind() {
		if (ProcessingService.isRunning()) {
			doBindService();
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putString("textIntValue", textIntValue.getText().toString());
		if (mImage != null) {
			outState.putParcelable(KEY_BITMAP, mImage);
		}
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		if (savedInstanceState != null) {
			textIntValue.setText(savedInstanceState.getString("textIntValue"));
			mImage = savedInstanceState.getParcelable(KEY_BITMAP);
			
			Bitmap image = mImage;
			mImageView.setImageBitmap(image);
			image = null;
		}
		super.onRestoreInstanceState(savedInstanceState);
	}

	/**
	 * Send data to the service
	 * 
	 * @param intvaluetosend
	 *            The data to send
	 */
	private void sendMessageToService(Bitmap bitmap) {
		if (mIsBound) {
			if (mServiceMessenger != null) {
				try {
					Message msg = Message.obtain(null,
							ProcessingService.MSG_SET_BITMAP_VALUE, 0, 0);
					msg.replyTo = mMessenger;

					Bundle b = new Bundle();
					b.putParcelable(KEY_BITMAP, bitmap);
					msg.setData(b);

					mServiceMessenger.send(msg);
				} catch (RemoteException e) {
				}
			}
		}
	}

	/**
	 * Bind this Activity to MyService
	 */
	private void doBindService() {
		bindService(new Intent(this, ProcessingService.class), mConnection,
				Context.BIND_AUTO_CREATE);
		mIsBound = true;
	}

	/**
	 * Un-bind this Activity to MyService
	 */
	private void doUnbindService() {
		if (mIsBound) {
			// If we have received the service, and hence registered with it,
			// then now is the time to unregister.
			if (mServiceMessenger != null) {
				try {
					Message msg = Message.obtain(null,
							ProcessingService.MSG_UNREGISTER_CLIENT);
					msg.replyTo = mMessenger;
					mServiceMessenger.send(msg);
				} catch (RemoteException e) {
					// There is nothing special we need to do if the service has
					// crashed.
				}
			}
			// Detach our existing connection.
			unbindService(mConnection);
			mIsBound = false;
		}
	}

	/**
	 * Handle button clicks
	 */
	@Override
	public void onClick(View v) {
		if (v.equals(mImageView)) {
			mIsSelectingPicture = true;
			Intent intent = new Intent();
			intent.setType("image/*");
			intent.setAction(Intent.ACTION_GET_CONTENT);
			startActivityForResult(
					Intent.createChooser(intent, "Select Picture"),
					SELECT_PICTURE);

			startService(new Intent(ImageFilterActivity.this,
					ProcessingService.class));
			doBindService();
		} else if (v.equals(btnStop)) {
			doUnbindService();
			stopService(new Intent(ImageFilterActivity.this,
					ProcessingService.class));
			android.os.Process.killProcess(android.os.Process.myPid());
		} else if (v.equals(btnFilter)) {
			if (mIsFinishFiltering == false) {
				doBindService();

				int reqWidth = mImageView.getMeasuredWidth();
				int reqHeight = mImageView.getMeasuredHeight();
				mImage = ImageUtil
						.decodeSampledBitmapFromResource(mSelectedImagePath,
								reqWidth, reqHeight, mIsHighQuality);

				sendMessageToService(mImage);
				DialogInterface.OnCancelListener listener = new DialogInterface.OnCancelListener() {
					@Override
					public void onCancel(DialogInterface dialog) {
						try {
							Message msg = Message.obtain(null,
									ProcessingService.MSG_STOP_TASK);
							mServiceMessenger.send(msg);
						} catch (RemoteException e) {
						}
						btnFilter.setEnabled(true);
						doUnbindService();
					}
				};
				mProgressDialog = ProgressDialog.show(ImageFilterActivity.this,
						getString(R.string.progressdialogtitle),
						getString(R.string.progressdialogcontent), true, true,
						listener);
			} else {
				new SaveImageTask().execute(mImage);
			}
			btnFilter.setEnabled(false);
		}
	}

	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		mIsSelectingPicture = false;
		if (resultCode == RESULT_OK) {
			if (requestCode == SELECT_PICTURE) {
				Uri selectedImageUri = data.getData();
				mSelectedImagePath = getPath(selectedImageUri);

				if (mImage != null) {
					mImage.recycle();
					mImage = null;
				}

				int reqWidth = mImageView.getMeasuredWidth();
				int reqHeight = mImageView.getMeasuredHeight();
				Bitmap image = ImageUtil.decodeSampledBitmapFromResource(
						mSelectedImagePath, reqWidth, reqHeight, false);

				mImageView.setImageBitmap(image);
				
				image = null;
				
				btnFilter.setEnabled(true);
				btnFilter.setText(getString(R.string.btnStart));
				textIntValue.setText("");
				mIsFinishFiltering = false;
			}
		}
	}

	private String getPath(Uri uri) {
		String[] projection = { MediaStore.Images.Media.DATA };
		Cursor cursor = managedQuery(uri, projection, null, null, null);
		int column_index = cursor
				.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		cursor.moveToFirst();
		return cursor.getString(column_index);
	}

	@Override
	public void onServiceConnected(ComponentName name, IBinder service) {
		mServiceMessenger = new Messenger(service);
		try {
			Message msg = Message.obtain(null,
					ProcessingService.MSG_REGISTER_CLIENT);
			msg.replyTo = mMessenger;
			mServiceMessenger.send(msg);
		} catch (RemoteException e) {
			// In this case the service has crashed before we could even do
			// anything with it
		}
	}

	@Override
	public void onServiceDisconnected(ComponentName name) {
		// This is called when the connection with the service has been
		// unexpectedly disconnected - process crashed.
		mServiceMessenger = null;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		try {
			doUnbindService();
		} catch (Throwable t) {
			Log.e(LOGTAG, "Failed to unbind from the service", t);
		}
		stopService(new Intent(ImageFilterActivity.this,
				ProcessingService.class));
	}

	@Override
	protected void onResume() {
		super.onResume();
		active = true;
	}

	@Override
	protected void onPause() {
		active = false;
		if (!ProcessingService.isProcessing() && ProcessingService.isRunning()
				&& !mIsSelectingPicture) {
			doUnbindService();
			stopService(new Intent(ImageFilterActivity.this,
					ProcessingService.class));
		}
		super.onPause();
	}

	public static boolean isActivityVisible() {
		return active;
	}

	/**
	 * Handle incoming messages from MyService
	 */
	private class IncomingMessageHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case ProcessingService.MSG_SET_INT_VALUE:
				textIntValue.setText("Time: " + msg.arg1 + ", Size: "
						+ mImage.getWidth() + " x " + mImage.getHeight());
				break;
			case ProcessingService.MSG_SET_BITMAP_VALUE:

				Bundle b = msg.getData();
				mImage = b.getParcelable(KEY_BITMAP);
				
				Bitmap image = mImage;
				mImageView.setImageBitmap(image);
				image = null;
				
				btnFilter.setText(getString(R.string.btnSave));
				btnFilter.setEnabled(true);
				if (mProgressDialog != null) {
					mProgressDialog.dismiss();
				}
				doUnbindService();
				stopService(new Intent(ImageFilterActivity.this,
						ProcessingService.class));
				mIsFinishFiltering = true;

				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	private class SaveImageTask extends AsyncTask<Bitmap, Integer, String> {
		@Override
		protected String doInBackground(Bitmap... params) {
			SimpleDateFormat dateFormat = new SimpleDateFormat(
					"yyyyMMdd_HHmmss");
			String fliename = "HugeHard_" + dateFormat.format(new Date());
			MediaStore.Images.Media.insertImage(contentResolver, params[0],
					fliename, "Created by ImageFilter");

			return null;
		}

		@Override
		protected void onPostExecute(String result) {
			Toast.makeText(getApplicationContext(),
					getString(R.string.saveImageToast), Toast.LENGTH_SHORT)
					.show();
		}
	}
}